#include "sys_config.h"
/*上位机-->下位机协议
{
	device_id：string
	command：string
	parameter：JSON
	{
		mode：string
		state：string
		speed：number
		electric：number
		pic_value：string
    }
}
* 字段解释：《鸿蒙小车设备概要设计说明书》
*/

// 数据缓冲区
char uart_sendBuff[128] = "";

/**
 * @brief 解析客户端发来的数据
 * @note  解析处理state键值对
 * @param parameter parameter键值对地址
 * @return 正确 0 错误 1 未定义指令 2
 */
static int Json_Ana_Net_State(cJSON *parameter)
{
    int ret = 0;
    if(parameter){
        if (globals_cmd_now.mode_cmd == DRIVING_MODE_MANUAL)
        {
            cJSON* speed = cJSON_GetObjectItem(parameter, "speed");
            cJSON* state = cJSON_GetObjectItem(parameter, "state");
            if(state && speed){
                globals_cmd_now.speed = speed->valueint;
                if(!strcmp(state->valuestring, "run")){
                    globals_cmd_now.state_cmd = DRIVING_STATUS_RUN;
                }else if(!strcmp(state->valuestring, "back")){
                    globals_cmd_now.state_cmd = DRIVING_STATUS_BACK;

                }else if(!strcmp(state->valuestring, "left")){
                    globals_cmd_now.state_cmd = DRIVING_STATUS_LEFT;

                }else if(!strcmp(state->valuestring, "right")){
                    globals_cmd_now.state_cmd = DRIVING_STATUS_RIGHT;

                }else if(!strcmp(state->valuestring, "stop")){
                    globals_cmd_now.state_cmd = DRIVING_STATUS_STOP;

                }else{
                    ret = 2;
                }

            }else{
                ret = 1;
            }
            state = NULL;
            speed = NULL;
        }
        else if(globals_cmd_now.mode_cmd == DRIVING_MODE_AUTO_TRACK)
        {
            globals_cmd_now.state_cmd = DRIVING_STATUS_AUTO_TRACK;
        }
        else if (globals_cmd_now.mode_cmd == DRIVING_MODE_DRIVELESS)
        {
            globals_cmd_now.state_cmd = DRIVING_STATUS_RUN;
        }
        else {
            ret = 1;
        }
        cJSON* beep = cJSON_GetObjectItem(parameter, "beep");
        cJSON* led  = cJSON_GetObjectItem(parameter, "led3");
        if(beep && led){
            if(!strcmp(beep->valuestring, "on")){
                globals_cmd_now.beep_cmd = BEEP_STATUS_ON;
            }else{
                globals_cmd_now.beep_cmd = BEEP_STATUS_OFF;
            }
            if(!strcmp(led->valuestring, "on")){
                globals_cmd_now.led_cmd = LED_STATUS_ON;
            }else{
                globals_cmd_now.led_cmd = LED_STATUS_OFF;
            }
        }else{
            ret = 1;
        }

        beep = NULL;
        led = NULL;
    }

    parameter = NULL;
    return ret;
}

/**
 * @brief 解析客户端发来的数据
 * @note  解析parameter键值对
 * @param parameter parameter键值对地址
 * @return 正确 0 错误 1 未定义指令 2
 */
static int Json_Ana_Net_Parameter(const cJSON *parameter)
{
    int ret = 0;
    if(parameter){
         cJSON* mode = cJSON_GetObjectItem(parameter, "mode");
            if(mode){
                if(!strcmp(mode->valuestring, "manual")){
                    globals_cmd_now.mode_cmd = DRIVING_MODE_MANUAL;
                    ret = Json_Ana_Net_State(parameter);
                }else if(!strcmp(mode->valuestring, "auto_track")){
                    globals_cmd_now.mode_cmd = DRIVING_MODE_AUTO_TRACK;
                    ret = Json_Ana_Net_State(parameter);
                }else if(!strcmp(mode->valuestring, "driveless")){
                    globals_cmd_now.mode_cmd = DRIVING_MODE_DRIVELESS;

                }else{
                    ret = 2;
                }
            }else{
                ret = 1;
            }
            mode = NULL;
    }
    parameter = NULL;
    return ret;
}

/**
 * @brief 解析客户端发来的数据
 * @note  解析command键值对
 * @param json 整个JSON地址
 * @return 正确 0 错误 1 未定义指令 2
 */
static int Json_Ana_Net_Command(cJSON *json)
{
    int ret = 0;
    if(json){
        cJSON* command = cJSON_GetObjectItem(json, "command");
        if(!strcmp(command->valuestring, "setstate")){
            globals_cmd_now.command = COMMAND_SET;
            cJSON* parameter = cJSON_GetObjectItem(json, "parameter");
            ret = Json_Ana_Net_Parameter(parameter);
            parameter = NULL;                                         
        }else if(!strcmp(command->valuestring, "getstate")){
            globals_cmd_now.command = COMMAND_GET;
        }else{
            ret = 2;
        }
        command = NULL;   
    }else{
        ret = 1;
    }
    json = NULL;
    return ret;
}


/**
 * @brief  封装Json数据
 * @note 将结构体中的数据取出进行Json打包
 * @param {*}
 * @return {*}
 */
void Json_Enc_SendToUart(te_driving_status_t car_status, char* device_id, u16_t speed)
{
    memset(uart_sendBuff, 0, sizeof(uart_sendBuff));
    if(!strcmp(device_id, "car")){
        switch (car_status)
        {
        case DRIVING_STATUS_ON:
            if (sprintf_s(uart_sendBuff, sizeof(uart_sendBuff), "{\"control\":{\"power\":\"on\"}}") > 0) {
                uart_send_buff(uart_sendBuff, strlen(uart_sendBuff));
            }
            break;
        case  DRIVING_STATUS_OFF:
            if (sprintf_s(uart_sendBuff, sizeof(uart_sendBuff), "{\"control\":{\"power\":\"off\"}}") > 0) {
                uart_send_buff(uart_sendBuff, strlen(uart_sendBuff));
            }
            break;        
        case  DRIVING_STATUS_STOP:
            if (sprintf_s(uart_sendBuff, sizeof(uart_sendBuff),"{\"control\":{\"turn\":\"stop\"}}") > 0) {
                uart_send_buff(uart_sendBuff, strlen(uart_sendBuff));
            }
            break;
        case  DRIVING_STATUS_RUN:
            if(sprintf_s(uart_sendBuff, sizeof(uart_sendBuff), "{\"control\":{\"turn\":\"run\",\"pwm\":{\"L_Motor\":%d,\"R_Motor\":%d}}}", 
                    speed, speed) > 0);
            uart_send_buff(uart_sendBuff, strlen(uart_sendBuff));
            break;
        case  DRIVING_STATUS_BACK:
            if (sprintf_s(uart_sendBuff, sizeof(uart_sendBuff),"{\"control\":{\"turn\":\"back\",\"pwm\":{\"L_Motor\":%d,\"R_Motor\":%d}}}",
                    speed, speed) > 0) {
                uart_send_buff(uart_sendBuff, strlen(uart_sendBuff));
            }
            break;
        case  DRIVING_STATUS_LEFT:
            if (sprintf_s(uart_sendBuff, sizeof(uart_sendBuff),"{\"control\":{\"turn\":\"left\",\"pwm\":{\"L_Motor\":%d,\"R_Motor\":%d}}}",
                    0, speed) > 0) {
                uart_send_buff(uart_sendBuff, strlen(uart_sendBuff));
            }
            break;
        case  DRIVING_STATUS_RIGHT:
            if (sprintf_s(uart_sendBuff, sizeof(uart_sendBuff),"{\"control\":{\"turn\":\"right\",\"pwm\":{\"L_Motor\":%d,\"R_Motor\":%d}}}",
                    speed, 0) > 0) {
                uart_send_buff(uart_sendBuff, strlen(uart_sendBuff));
            }
            break;
        case  DRIVING_STATUS_AUTO_TRACK:
            if (sprintf_s(uart_sendBuff, sizeof(uart_sendBuff),"{\"control\":{\"power\":\"off\", \"turn\":\"auto_track\"}}") > 0) {
                uart_send_buff(uart_sendBuff, strlen(uart_sendBuff));
            }
            break;
        default:
            break;
        }
    }

}

// void Json_Enc_SendToNet(void);

char * Json_Enc_SendToNet(void)
{
    char * data = (char *)malloc(512);
    memset(data,0,512);

    char * dev_id = (char *)malloc(10);
    char * command = (char *)malloc(10);
    char * mode = (char *)malloc(20);
    char * state = (char *)malloc(10);
    char * beep = (char *)malloc(10);
    char * led = (char *)malloc(10);
    memset(dev_id,0,10);
    memset(command,0,10);
    memset(mode,0,20);
    memset(state,0,10);
    memset(beep,0,10);
    memset(led,0,10);

    switch(globals_cmd_now.device_id){
        case DEVICE_CAR:
            strcpy(dev_id,"car");
            break;
        case DEVICE_BEEP:
            strcpy(dev_id,"beep");
            break;
        case DEVICE_CAMERA:
            strcpy(dev_id,"camera");
            break;
    }
    switch(globals_cmd_now.command){
        case COMMAND_SET:
            strcpy(command,"setstate");
            break;
        case COMMAND_GET:
            strcpy(command,"getstate");
            break;
    }
    switch(globals_cmd_now.mode_cmd){
        case DRIVING_MODE_MANUAL:
            strcpy(mode,"manual");
            break;
        case DRIVING_MODE_AUTO_TRACK:
            strcpy(mode,"auto_tarck");
            break;
        case DRIVING_MODE_DRIVELESS:
            strcpy(mode,"driveless");
            break;
    }
    switch(globals_cmd_now.state_cmd){
        case DRIVING_STATUS_RUN:
            strcpy(state,"run");
            break;
        case DRIVING_STATUS_BACK:
            strcpy(state,"back");
            break;
        case DRIVING_STATUS_LEFT:
            strcpy(state,"left");
            break;
        case DRIVING_STATUS_RIGHT:
            strcpy(state,"right");
            break;
        case DRIVING_STATUS_STOP:
            strcpy(state,"stop");
            break;
    }
    switch(globals_cmd_now.beep_cmd){
        case BEEP_STATUS_ON:
            strcpy(beep,"on");
            break;
        case BEEP_STATUS_OFF:
            strcpy(beep,"off");
            break;
    }
    switch(globals_cmd_now.led_cmd){
        case LED_STATUS_ON:
            strcpy(led,"on");
            break;
        case LED_STATUS_OFF:
            strcpy(led,"off");
            break;
    }

    sprintf(data,
        "{\"device_id\":\"%s\",\"command\":\"%s\",\"response\":%d,\"parameter\":{\"mode\":\"%s\",\"state\":\"%s\",\"beep\":\"%s\",\"led\":\"%s\",\"speed\":%d,\"electric\":%d}}",
        dev_id,//设备id
        command,//控制指令
        globals_cmd_now.response,//回传结果
        mode,//控制模式
        state,//状态
        beep,
        led,
        globals_cmd_now.speed,//速度
        globals_car_status.power//电量
        );

    free(dev_id);
    free(command);
    free(mode);
    free(state);
    free(led);

    return data;
}

/**
 * @brief 解析单片机JSON数据
 * @note 解析存入全局变量结构体
 * @param recv_data 数据缓存区地址
 * @return 正确 0 错误 -1
 */
int Json_Ana_RecvFromUart(char *recv_data)
{
    int ret = 0;
    cJSON *json_root = cJSON_Parse((const char *)recv_data);
    if (json_root) {
        cJSON *json_status = cJSON_GetObjectItem(json_root, "status");
        if (json_status) {
            cJSON *json_distance = cJSON_GetObjectItem(json_status, "distance");
            if (json_distance) {
                globals_car_status.distance = json_distance->valueint;
                printf("globals_car_status.distance: %d\r\n", globals_car_status.distance);
            }else{
                ret = -1;
            }
            json_distance = NULL;

            cJSON *json_carPower = cJSON_GetObjectItem(json_status, "carPower");
            if (json_carPower) {
                globals_car_status.power = json_carPower->valueint/1000;
                printf("globals_car_status.power: %d\r\n", globals_car_status.power);
            }else{
                ret = -1;
            }
            json_carPower = NULL;

            cJSON *json_L_speed = cJSON_GetObjectItem(json_status, "L_speed");
            cJSON *json_R_speed = cJSON_GetObjectItem(json_status, "R_speed");
            if (json_R_speed && json_L_speed) {
                //车轮转速（转/分，RPM） = 脉冲计数 / 每转脉冲数 × 60（秒/分）
                int l_rpm = 0;
                int r_rpm = 0;
                //车的速度：轮胎周长*车轮转速*60/1000，单位km/h
                int l_speed = 0;
                int r_speed = 0;
                globals_car_status.left_speed = json_L_speed->valueint;
                globals_car_status.right_speed = json_R_speed->valueint;

            }else{
                ret = -1;
            }
            json_L_speed = NULL;
            json_R_speed = NULL;
        }else{
            ret = -1;
        }
        json_status = NULL;
    }else{
        ret = -1;
    }
    cJSON_Delete(json_root);
    json_root = NULL;

    //加锁 -- 更新车辆状态, 更新oled
    Oled_Update_Carstatus();

    return ret;
}


/**
 * @brief 解析客户端发来的数据
 * @note 
 * @param recv_data 数据缓存区地址
 * @return 正确 0 错误 1 未定义指令 2
 */
int Json_Ana_RecvFromNet(char* recv_data)
{
    int ret = 0;
    set_led(true);
    cJSON* json = cJSON_Parse(recv_data);
    if(json){
        cJSON* device_id = cJSON_GetObjectItem(json, "device_id");
        if(device_id){
            ret = Json_Ana_Net_Command(json);
        }else{
            ret = 1;
        }
        device_id = NULL;
    }else{
        ret = 1;
    }
    cJSON_Delete(json);

    set_led(false);
    json = NULL;
    return ret;
}